package net.corda.core.contracts

import net.corda.core.identity.Party
import net.corda.core.internal.extractFile
import net.corda.core.serialization.CordaSerializable
import java.io.FileNotFoundException
import java.io.InputStream
import java.io.OutputStream
import java.util.jar.JarInputStream

/**
 * An attachment is a ZIP (or an optionally signed JAR) that contains one or more files. Attachments are meant to
 * contain public static data which can be referenced from transactions and utilised from contracts. Good examples
 * of how attachments are meant to be used include:
 * - Calendar data
 * - Fixes (e.g. LIBOR)
 * - Smart contract code
 * - Legal documents
 * - Facts generated by oracles which might be reused a lot
 */
@CordaSerializable
interface Attachment : NamedByHash {
    fun open(): InputStream
    fun openAsJAR(): JarInputStream {
        val stream = open()
        try {
            return JarInputStream(stream)
        } catch (t: Throwable) {
            stream.use { throw t }
        }
    }

    /**
     * Finds the named file case insensitively and copies it to the output stream.
     * @throws FileNotFoundException if the given path doesn't exist in the attachment.
     */
    fun extractFile(path: String, outputTo: OutputStream) = openAsJAR().use { it.extractFile(path, outputTo) }

    /**
     * The parties that have correctly signed the whole attachment.
     * Can be empty, for example non-contract attachments won't be necessarily be signed.
     */
    val signers: List<Party>
}
